///////////////////////////////////////////////////////////////////////////////
//
// lighthouse3D - 3D Software Library
//
// File: C3DLibrary.h
//
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2003-2013 Marcus Reinhardt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
///////////////////////////////////////////////////////////////////////////////
//
// You can find a copy of the GNU General Public License (gpl.txt) in the
// directory of the library.
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////
//
// lighthouse3D 3D Library - A 3D Software Library
//
// Version - 0.7.0.2
//
///////////////////////////////////////////////////////////////////////////////////
//
// Developed by Marcus Reinhardt 2003-2013
// For the latest release and further information see 
//
//                      http://code.google.com/p/lighthouse3d/
//
///////////////////////////////////////////////////////////////////////////////////

#ifndef _C3DLibrary_H_
#define _C3DLibrary_H_

#include <string.h>

#include "C2DScreen.h"
#include "CFileHandler.h"
#include "CFogSynthesis.h"
#include "CLighting.h"
#include "CMathe3D.h"
#include "CMeshStorage.h"
#include "CObjects.h"
#include "CCamera.h"
#include "CZBuffer.h"
#ifdef __MULTI_CORE_SUPPORT
  #include "lh3dmthread.h"
#endif

#define _lighthouse3DLogo_		"lh3dlogo.bmp"

#ifdef __MULTI_CORE_SUPPORT
    #define __THREAD_STATE_NOT_AVAILABLE    0
    #define __THREAD_STATE_READY			1
    #define __THREAD_STATE_PROCESS_REQUEST	2
    #define __THREAD_STATE_PROCESSING    	3
    #define __THREAD_STATE_RENDER_REQUEST	4
    #define __THREAD_STATE_RENDERING     	5
    #define __THREAD_STATE_JOIN_REQUEST	    6
    #define __THREAD_STATE_JOINING       	7
    #define __THREAD_STATE_FINISHED         8 

    #define __CPU_CORES_SUPPORTED           4
#endif

///////////////////////////////////////////////////////////////////////////////////
//  class C3DLibrary : Root class to handle the library
///////////////////////////////////////////////////////////////////////////////////

//! Root class to handle the library functions
class C3DLibrary {

  public:
  
    ///////////////////////////////////////////////////////////////////////////////
    // constructor/destructor
    ///////////////////////////////////////////////////////////////////////////////
    C3DLibrary();
    ~C3DLibrary();

    ///////////////////////////////////////////////////////////////////////////////
    // library setup functions
    ///////////////////////////////////////////////////////////////////////////////
	void setupUseInternalScreen();
    void setupColDetection(int ColDetection);
    void setupBFCulling(int bfCulling);
    void setupFSAAFilter(int filter);
    void setupTexFilter(int filter);
    void setupLighting(int lighting);
    void setupRenderer(int renderer);
    void setupShader(int shader);
    void setupFogSynthesis(int fog);
    void setupIncShader();
    void setupLogo(int logo);

    ///////////////////////////////////////////////////////////////////////////////
    // multi core support
    ///////////////////////////////////////////////////////////////////////////////
#ifdef __MULTI_CORE_SUPPORT
    unsigned long workerThread(unsigned char nrThreadParams, unsigned char *threadParams);
    void          setThreadState(unsigned char workerThreadState);
    unsigned char checkThreadState(unsigned char workerThreadState);
#endif
	
	///////////////////////////////////////////////////////////////////////////////
    // meshStorage function
    ///////////////////////////////////////////////////////////////////////////////
    //
    // In the moment there is no possibility to remove any texs, triangles or 
    // vertexes separately, but this is no real problem, because those three 
    // structs don't require that much memory.
    //
    // For Example:
    // Let's consider a mesh with 1000 vertexes:
	//
    // There are 16 elements each consuming 8 Bytes in one struct.
    // So such a mesh consumes 1000 x 16 x 8 = 128000 Bytes, which is really not
    // that much... :)
    //
    // But you still have the possibility to remove the complete mesh with
    // removeMesh(), it will erase the whole mesh including texs, vertexes and
	// triangles.
    //
    ///////////////////////////////////////////////////////////////////////////////    
    bool addNewMesh();
    bool addNewTriangle(int mesh, TMeshTriangle face);
    bool addNewVertex(int mesh, TMeshVertex vert);
    bool setChangedVertex(int mesh, int vert, TMeshVertex vertex);
    bool setScreenVertex(int mesh, int vert, TMeshVertex vertex);
    bool setVertex(int mesh, int vert, TMeshVertex vertex);
    bool removeMesh(int mesh);
    int  getMeshCount();
    int  getTexCount();

	CMeshData*     getMesh(int mesh);
	TMeshTriangle* getTriangle(int mesh, int face);
	TMeshVertex*   getVertex(int mesh, int vert);

	///////////////////////////////////////////////////////////////////////////////
	// geometric functions on the original data
	///////////////////////////////////////////////////////////////////////////////
	bool rotateOriginalData(int mesh, int xr, int yr, int zr);

	///////////////////////////////////////////////////////////////////////////////
	// geometric functions on the transformed data
	///////////////////////////////////////////////////////////////////////////////
	bool         backFaceCulling(int mesh);
	bool         calcPlaneNormals(int mesh);
	bool         calcVertexNormals(int mesh);
	bool         geometricPreparation(int mesh);
	bool         resetMesh(int mesh);
	bool         projection(int mesh);
	bool         rotation(int mesh);
	bool         rotationAroundP(int mesh, TMeshVertex p, int rx, int ry, int rz);
	bool         rotationVAroundP(TMeshVertex *v, TMeshVertex p, int rx, int ry, int rz);
	bool         skalation(int mesh);
	bool         transformCamera(int mesh);
	bool         transformNormals(int mesh);
	bool         translation(int mesh);
	bool         translateToOrigin(int mesh);
    bool         translateToPosition(int mesh);
	bool         zClipping(int mesh);
    bool         complgeometricops(int mesh);	
    void         clearPositionMap(int mesh);
    void         initPositionMap(int mesh);
    T3DPosition  getPositionMap(int mesh);
	void         setPositionMap(int mesh, T3DPosition posMap);
    bool         transformLights();

	///////////////////////////////////////////////////////////////////////////////
	// render functions
	///////////////////////////////////////////////////////////////////////////////
	bool         setupDDrawInterface(char* memStart, long nextScanLine);
    bool         renderPixelCPU(unsigned char cpu, int x, int y, unsigned int color);
	bool         renderPixel(int x, int y, unsigned int color);
	bool         renderLine(int x1, int y1, int x2, int y2, unsigned int color);
	bool         renderBox(int x1, int y1, int x2, int y2, int y3, unsigned int color1, unsigned int color2, unsigned int color3);
	bool         renderHLine(unsigned char cpu,TLineData *LT);
	bool         renderTriangle(unsigned char cpu,int face);
	bool         renderScene();
	bool         quickSortTriangleList( int iLo, int iHi );
	int          buildTriangleList();
	int          getMinSizeX() { return 0; }
	int          getMinSizeY() { return 0; }
	int          getMaxSizeX() { return screen2D.getSizeX(); }
	int          getMaxSizeY() { return screen2D.getSizeY(); }
	unsigned int getPixel(int x, int y) { return screen2D.getPixel(x, y); }
	unsigned int getPixelRelative(int x, int y, int relX, int relY) { return screen2D.getPixelRelative(x, y, relX, relY); }
	
    ///////////////////////////////////////////////////////////////////////////////
    // other functions
    ///////////////////////////////////////////////////////////////////////////////
    void release();

    ///////////////////////////////////////////////////////////////////////////////
    // meshStorage
    ///////////////////////////////////////////////////////////////////////////////
    CMeshStorage m_meshStorage;

    ///////////////////////////////////////////////////////////////////////////////
    // Mathematics library for 3D-routines (rotation,...)
    ///////////////////////////////////////////////////////////////////////////////
    CMathe3D mathe3D;

    ///////////////////////////////////////////////////////////////////////////////
    // Create some objects internally
    ///////////////////////////////////////////////////////////////////////////////
    CObjects objectCreator;

    ///////////////////////////////////////////////////////////////////////////////
	// A 2D screen handler
    ///////////////////////////////////////////////////////////////////////////////
#ifdef __MULTI_CORE_SUPPORT
	// If rendering on multiple CPUs we need multiple screen to render to
    C2DScreen *screen2DCPU[__CPU_CORES_SUPPORTED];
#endif
    C2DScreen screen2D;

    ///////////////////////////////////////////////////////////////////////////////
    // A zBuffer handler
    ///////////////////////////////////////////////////////////////////////////////
#ifdef __MULTI_CORE_SUPPORT
	// If rendering on multiple CPUs we need multiple depth buffer to save z data to
	CZBuffer *zBufferCPU[__CPU_CORES_SUPPORTED];
#endif
	CZBuffer zBuffer;

    ///////////////////////////////////////////////////////////////////////////////
    // A file handler class
    ///////////////////////////////////////////////////////////////////////////////
    CFileHandler fileHandler;

    ///////////////////////////////////////////////////////////////////////////////
    // A lighting handler class
    ///////////////////////////////////////////////////////////////////////////////
    CLighting lightingHandler;

    ///////////////////////////////////////////////////////////////////////////////
    // A Camera handler class
    ///////////////////////////////////////////////////////////////////////////////
    CCamera cameraHandler;

    ///////////////////////////////////////////////////////////////////////////////
	// Fog synthesis
    ///////////////////////////////////////////////////////////////////////////////
#ifdef __MULTI_CORE_SUPPORT
	CFogSynthesis *fogSynthesisCPU[__CPU_CORES_SUPPORTED];
#endif
    CFogSynthesis fogSynthesis;

    ///////////////////////////////////////////////////////////////////////////////
    // Library Setup
    ///////////////////////////////////////////////////////////////////////////////
    TLibrarySetup libSetup;

    ///////////////////////////////////////////////////////////////////////////////
    // library informations
    ///////////////////////////////////////////////////////////////////////////////
    TLibraryInfo libInfo;

    ///////////////////////////////////////////////////////////////////////////////
    // Line Information for renderHLine()
    ///////////////////////////////////////////////////////////////////////////////

	///////////////////////////////////////////////////////////////////////////////
	// Other variables
	///////////////////////////////////////////////////////////////////////////////
	int  opticalCorrectness;
	int  renderedTrianglesCount;
	int  renderedPixelsCount;
	int  renderedHLinesCount;
	int  screenSizeX, screenSizeY;
	int  screenCenterX, screenCenterY;
    int  sizeTriangleList;
	
	TPictureData logo;

	TOrderedTrList zOrderTrList[_sizeOfTriangleList_];

	///////////////////////////////////////////////////////////////////////////////
	// Multi Core support variables
	///////////////////////////////////////////////////////////////////////////////
#ifdef __MULTI_CORE_SUPPORT
	unsigned char threadState[256];
	unsigned char numberWorkerThreads;
#endif
};

#endif
